package gamecfg

import (
	"fmt"
	"gamesdk/wanyu/server/protogo/public"
	cst "gamesdk/wanyu/server/engine/globaldef/consts"
	errors "gamesdk/wanyu/server/engine/wperror"
	"regexp"
)

/*
	游戏配置包，实现原始配置文件解析、保存、配置按游戏场次分类，并提供获取游戏配置的接口
*/

var (

	//游戏纬度的游戏配置，所有数据从rawGameCfg解析而来，gameCfg如果不为空表示配置一定正确
	gameCfg *GameCfg
	//游戏场次纬度的游戏配置，所有数据从rawGameCfg解析而来，gameKindCfgs如果不为空表示配置一定正确
	//gameKindCfgs []KindCfg
	//水位信息，<代理商id、水位>
	agentInfos map[string]AgentInfo
)

//系统水位
type SysPoolData struct {

	//当前输赢
	CurrentPool int64

	//当前输赢(不受点控等影响)
	CurrentPoolActual int64

	//群控等级
	GroupCTLevel int32

	PoolData []SysPool
}

//系统水位
type SysPool struct {

	//系统当前输赢
	Value int64

	//杀放率，取值[-1, 1]
	Rate float32
}

//个人水位
type PersonPool struct {
	//累计重置金额
	Bottom int64
	//放分线（win代笔需要让玩家赢钱），左闭
	WinLine int64
	//杀分线（lose代表需要让玩家输钱），右开
	LoseLine int64
}

//游戏配置
type GameCfg struct {
	//无操作时踢出玩家的时间，单位局或秒
	KickTime int
	//游戏就绪到游戏正式开始之间的时间间隔，单位秒
	StartWaitTime int
	//游戏开局最少玩家个数
	MinPlayerCnt int
	//一局游戏最多玩家个数
	MaxPlayerCnt int
	//税率，取值0-1之间的浮点数
	TaxRate float32
	//未充值匹配机器人的开关，如果开启，未充值的玩家只能和一堆机器人一起玩
	EnableRobotIfNoPay bool
	//ip匹配开关，如果开启，相同ip的玩家不能在同一房间
	EnableIp bool
	//个人赢钱时，输赢值多增加百分比,取值0-1之间的浮点数
	WinInvisibleTaxRate float32
	//机器人赢钱时，血池少增加百分比,取值0-1之间的浮点数
	RobotWinInvisibleTaxRate float32
}

//游戏子场次配置
type KindCfg struct {
	//场次id
	KindId uint32
	//当前场次系统赢钱数，为负代笔系统输钱
	//WinMoney int64
	//本场次游戏底分
	BaseMoney int64
	//本场次进房至少多少钱
	MinMoney int64
	//本场次进房至多多少钱，-1表示无上限限制
	MaxMoney int64
	//机器人入场携带钱最少数
	RobotMinMoney int64
	//机器人入场携带钱最大数
	RobotMaxMoney int64
	//本场次是否允许机器人进入房间的开关
	EnableRobot bool
	//房间服务费
	TableServerCharge int64
	//每局最高赢钱限制
	RoundMaxWinMoney int64
	//本场次倍数
	BaseMultiple uint32
}

//代理商水位，涵盖系统水位、个人水位、杀/放概率
type AgentInfo struct {
	AgentId string
	//个人放率
	PersonWinRate float32
	//个人杀率
	PersonLoseRate float32
	//个人水位
	PersonPool []PersonPool
	//系统水位，<场次id、水位配置>
	SysPool map[uint32]SysPoolData
	//游戏场次
	KindCfgs []KindCfg
}



func GetAgentInfos() map[string]AgentInfo {
	return agentInfos
}

func GetGameCfg() GameCfg {
	errors.CheckError(nil != gameCfg, fmt.Errorf("error call function"))
	return *gameCfg
}


//获取已解析好的通用配置，返回的是副本，如果未能成功向romsrv获取配置或配置解析错误或kindId不存在，此函数将抛出panic
func GetGeneralCfg(kindId uint32, agentId string) (GameCfg, KindCfg) {
	agentInfo, ok := agentInfos[agentId]
	errors.CheckError(ok, fmt.Errorf("can not find agent info, input agent id = %v", agentId))
	for _, v := range agentInfo.KindCfgs {
		if v.KindId == kindId {
			return *gameCfg, v
		}
	}

	errors.CheckError(false, fmt.Errorf("can not find kind info, input kind id = %v", kindId))
	return GameCfg{}, KindCfg{}

	// errors.Check(nil != gameCfg && nil != gameKindCfgs, errors.ErrorGameCfg, "invalid game cfg")
	// for _, v := range gameKindCfgs {
	// 	if v.KindId == kindId {
	// 		return *gameCfg, v
	// 	}
	// }

	// errors.Check(false, errors.ErrorGameCfg, "invalid kind id")
	// return GameCfg{}, KindCfg{}
}

// func GetAll() (GameCfg, []KindCfg) {
// 	errors.Check(nil != gameCfg || nil != gameKindCfgs, fmt.Errorf("error call function"))
// 	return *gameCfg, gameKindCfgs
// }



// func GetKindIds() []uint32 {
// 	kindIds := make([]uint32, len(gameKindCfgs))
// 	for k, v := range gameKindCfgs {
// 		kindIds[k] = v.KindId
// 	}

// 	return kindIds
// }

//通过正则，根据微服务名解析游戏类型，如果解析失败或未知游戏类型，本函数将抛出恐慌
func ParseGameType(microName string) public.GameType {
	exp := regexp.MustCompile("^wind.platform.api.game.([a-z]+).*$")

	ret := exp.FindStringSubmatch(microName)
	errors.Check(2 == len(ret), errors.ErrorGameCfg, "invalid micro service name")

	gameType, ok := cst.GamesName[ret[1]]
	errors.Check(ok, errors.ErrorGameCfg, "invalid game type")
	return gameType
}
